package com.lanhao.aot.util;

import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

public class RSAUtils {
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 256;

    /**
     * 获取密钥对
     * 
     * @return 密钥对
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(2048);
        return generator.generateKeyPair();
    }

    /**
     * 获取私钥
     * 
     * @param privateKey 私钥字符串
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 获取公钥
     * 
     * @param publicKey 公钥字符串
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        return keyFactory.generatePublic(keySpec);
    }
    
    /**
     * RSA加密
     * 
     * @param data 待加密数据
     * @param publicKey 公钥
     * @return
     */
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        int inputLen = data.getBytes().length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
        // 加密后的字符串
        return new String(Base64.encodeBase64String(encryptedData));
    }

    /**
     * RSA解密
     * 
     * @param data 待解密数据
     * @param privateKey 私钥
     * @return
     */
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dataBytes = Base64.decodeBase64(data);
        int inputLen = dataBytes.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段解密
        while (inputLen - offset > 0) {
            if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        // 解密后的内容 
        return new String(decryptedData, "UTF-8");
    }

    /**
     * 签名
     * 
     * @param data 待签名数据
     * @param privateKey 私钥
     * @return 签名
     */
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        byte[] keyBytes = privateKey.getEncoded();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey key = keyFactory.generatePrivate(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(key);
        signature.update(data.getBytes());
        return new String(Base64.encodeBase64(signature.sign()));
    }

    /**
     * 验签
     * 
     * @param srcData 原始字符串
     * @param publicKey 公钥
     * @param sign 签名
     * @return 是否验签通过
     */
    public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
        byte[] keyBytes = publicKey.getEncoded();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey key = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(key);
        signature.update(srcData.getBytes());
        return signature.verify(Base64.decodeBase64(sign.getBytes()));
    }

    public static void main(String[] args) {
        try {
            // 生成密钥对
//            KeyPair keyPair = getKeyPair();
//            String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
//            String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
//            System.out.println("私钥:" + privateKey);
//            System.out.println("公钥:" + publicKey);
        	
        	String privateKey="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsUE9LJxsCMi0haSCgJFuuff2lqujsu6sms14RKtMZF1dZ5ciZnLwjtABjl4HxE+dhb2x1OTW6UuI2UdrND44K/o+AZeHF3bfC7sa/H4YGhlqAd2kJxiQCKjTWFfpPIgMeNDv93tpPc0W8a8n+nyVOoU4gYyPAfWq6bbIN4vkcN9ID3Bw7qbqhAWWpmMsm+9B8/1r2S2I5qSTVnTdtnbpQ5VsmtY4k1QJWXvpvwdbsW8lBAW0bSpS5TsjT9WPIZe2EWXQ05b8D1p2yMzBvzNOr9VQCkNhp1ZbJ7eTgP8xBD1HqHFYKdWga4vGKwxZtodpgVP9LpjMIQZFVZrU5YQDbAgMBAAECggEAVT2VPDQoJDn2IWUEArR5tiQVafLWLuXXkNmCWzO4Id1uFMabKYJjf7X3y0yTt1KFT6nzGTon3fhKd1yexHpBZibvjjDYMy2vTfsYzksl3exwsMRhbbha78c5Q/6zSJomuLZWRwwLKup3QPKBhjfsGK2rHFJuyTZBqd/CCSSS3uXdRoDHmXC4g/PqMj5Ex0CnBIpxKVNC0f4nUDMiVy4sV9vnWjEJIiB+M/HHQldOCldBWigo0SwkywmHqgnLfZTA6xuoHeEWNv8Fpg0hYYS0YxSYvdpUKYCVwgPEfi1crhYKrJ2ZHVuFmEXEMDWoeFcApgTz6ktyC814SGBUfisTAQKBgQDpXjiZhzOeRU/QEQMb3hmgrjc8w33xmUGT9puOkAZlmlUIE/BDJkJRmOFja3cG/ZZ6pbH3oVfJ6n8Lc/OCVVnWzR75lpyeZ2XKfxIcCrMZSAIDJPKw/0RhXY+jna3hMvItTm2HwZIp7ZqIHuh0nBQ+tsNIO2tSLU3t6KW1Vqj/OwKBgQC9Bk42mRsZATrGSKNmiAsKVoY/tmJVIykcdc7BY6K8rSY8OHL0fQ9S7ZBTjKBXtJyYiXv4i6DwVnv0Ld6mnFPUxDScNoywGmTJLbzdEWHy7hjvgAGBf9F9q5cWwyPB1ypO4UuE424h4MGiEeprYY4rNcvA/LcZ547hUVU5IVsq4QKBgQChnA9kOt4DSAqqk21suhVTUfKM0PECA9kHJ6u4QYM8j3E9Y9lqFy+sJExJtl06aRjxnJevXntWKF+MxeKnqoXJnElMHQIfLImwfulCpCI9asGB/e9XpZ9sMgfMDeEhaE+QEpUFg4a+JH50r7rZLlFS0OxRtFxxD1C9ZfSDrRzhiwKBgAYe0CWAa5oxqf+FlpTZTtI03v/tHd3313rubZVhboGBcb19bmtwKTDcNFIgOYjddjySJwtzKfDePAE6Av2ODkDTYYi1U3TYRe8lpfnaeDtvbitDD8lrpBLXnXrFMsEyAFKxhMp2urgqGNrwjZCQhhPsF/7Vr/AMyVmOUp4Y8GTBAoGBALYA9NpCi0sbEjeW6297C9FHiQxB+Sh63uLhaNNeZHP0fAmFcVjH0uJ9OWyTEVeNgwXrP0AjgflXG68l4Vafm0Sg4XWSiO84uaVer3oE+xBRQNWE0rb26h0AtrfqDoWpMGYEpyFWDcU1NNAWTZAm/I98iK5r6DZitlbZS4hwzSc9";
//        	String publicKey ="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmIDVi0PB2GI7nVuZ4Hx+fyqJdJrVucyyxsQt5Z52eyr+luJ3HW0cHKIyQChpw2xrTyscr/JOYwnMgceRo29lb2w2ILUq5Y7uPM6GfFPM1anoq4br8/XOhOuHLjPXfSaxt9azSZG60jmvWvwNTau2Uu2vlTy07PYDY5c4RpukyaQIDAQAB";
        	
        	String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArFBPSycbAjItIWkgoCRbrn39paro7LurJrNeESrTGRdXWeXImZy8I7QAY5eB8RPnYW9sdTk1ulLiNlHazQ+OCv6PgGXhxd23wu7Gvx+GBoZagHdpCcYkAio01hX6TyIDHjQ7/d7aT3NFvGvJ/p8lTqFOIGMjwH1qum2yDeL5HDfSA9wcO6m6oQFlqZjLJvvQfP9a9ktiOakk1Z03bZ26UOVbJrWOJNUCVl76b8HW7FvJQQFtG0qUuU7I0/VjyGXthFl0NOW/A9adsjMwb8zTq/VUApDYadWWye3k4D/MQQ9R6hxWCnVoGuLxisMWbaHaYFT/S6YzCEGRVWa1OWEA2wIDAQAB";

        	
            // RSA加密
            String data = "{'businessNo':'201907111100300608490500435394','extendInfo':{'calcServiceFeeFlag':'1','calcCarriageFlag':'0','orderNo':'zbcTest'},'goodsDTO':{'itemDTOList':[{'extendInfo':{},'itemCode':'456789','itemDesc':'XX_TShirt','itemQuantity':2,'itemType':'WearWithoutUnderwear','lineNo':'1','unitPrice':20000}],'priceUnit':'CENT','totalPrice':40000.000000,'volumeUnit':'CUBIC_CENTIMETER','weightUnit':'GRAM'},'receiverDTO':{'address':'test ','area':'','city':'Test','linkName':'Test','mobile':'1311','province':'11','storeCode':'Test','zipcode':'142180'},'senderDTO':{'address':'MSK FIVE','linkName':'yang Liu','mobile':'15800631882'},'waybillNo':'ABCDEF-9QESDS-1222'}";
//            String encryptData = encrypt(data, getPublicKey(publicKey));
            
            String encryptData = "SU7ji5XarZthAJPvDT5mNzVpcISYJxiYqycRRzb5VDXZEUtY3NQqBAlYC1N7K3BimEnFueh9up0jaFMs2t0JLPd%2FyzI%2F0K8ezKGpgzq+qG17uUDVAy1j67o5EDsXPFlfkN3UQDy9KwyGG3VvA6NwlUALHZDUDLWTaWWmWrYagMV67zN+SiEk91oNnEg1VC+KA4ckSOYZy5TeuvxotZr8W4XxJIpHWSYosCYXkiXEkoyg+84TAl4FHkORazSpDUozTpk%2FmeyF2eupArBBn8SjLR8m49UsZg3zA6CVT6wzefhKAJgubQE8HRgBuLOGIqmhICfkiLlFxbvpk0%2FjNVnX4ADwH2ZFVGscoYwuVFBD3VjrxiSsnT4QlLp9BYfrGl+Nu0dWW8GQ5AD4R1OKSdoSHBDiJvvGqcvUsqhA2fgQgziFferU+eo6u14TTXQ+j1Cqk2eXa2XmBTIggeYzShrta7rIA5X0qYAH5JTQz7FmAeNzKygsZe3W6eF7NzFE7kAMh6F%2F6s8b8vw4zku06XqoQPY9NMKrESqi3pIvMgsyY1eiGpyTFd+tK+89FchWCn7TZ92NzYcpqdfd03ba3nGwgWYyHaGXhULdnFg0QIs8v0hHnLiS9kcTCVmcdy88DBlYpfHJXzoNf4ZAy1ZEBHQ7wgKNTePonFwyuOAXr9hU5nWTVc0%2FTxWSlo+nHr7KYJdCQVOdsO9kRTOwEW6OZ9JWd6iRBwAzfHO1seL4cty5HJdOjWmMpF1Pbt+XtqfbNoM2f9J6jUSnBCusOVWdB64BWy1RW%2F9cTRMWIoGwzeCD9KN86R6YJ48S%2FZtIn6ioKEhnycghcpAIrd9NN81Olrh3sCPpU3pmUZGfO24bq6TXMLVW67gZ8g82RbkPTQ2EfOUDY5NILV5Ql%2Fu76N+zu7eT8zirQucjRi89PNDAFdwcMaI7IaWBiDFCs1oXgcNZRgDqo+uhw4tS5oFc2jhK%2Fl6gXurteT3D+1L+SRfz1%2FebUINPQVhf4vB4VXZJ06gtNUUYSd0FmPyYQDgiAVhTNJcYTFt3Y7g7IsY1cXy6%2FryLS4igc5HxkOvmC8AZhneMVBMVajVDmUx7HcdEcek1k0MEmtbe1HW7Wsy2VcJJX8Cqv1ZAhmZ9L9SdQ%2Fw6IxLoF3N9nfazwxGYHgc2A34Tt7Jsr97QlLnadmibSsqGwGioZGscylnDqbafkza845gA3IZ0OC09lL5wMvQZHUVhK%2FyGMTwbvlA%2FM+oJB8%2Fvu4xxtjjDdsyXou5vszBm27PwGE61LivfgqhRkwjK%2FF4KQevi%2FEAuHRtV%2FbuTRS9bMxhEviKXC27tsrTMoWxsZh2DK24sOtjEf4c7jyVoCYQtUETf82Ez9aKvF0oDdynJIUq3QaluC3q3E7r3KZbtDOqozvDq43NsfTInhccMmB4v8SO8Qg67kZW2ugH9zeAJ%2FoH5FCqF9q+NtLRz11nI5YYUSkkYwRPpaFfFrIu9m9cX7HhhI5gCGfKrHpilop4EubLXIjO4U56BpOoMenPiifPPNYnnxppKwMlDkUtejOX5OCHK7VeGjGzBI7Jl0bM+MxENBBebSbTSD+KVLnV%2FdtXAsyV6G9MFzC2q2sGIcrAiy4i1yavcRcdnMByf0tgHVWl1ChzX2vH+7MymB0zT%2FQZPOeYMzx2JNaNE4L7H54wbxtAU%2FyAKNIZlxiR4bcdqj7WOCCwd3ryrjDa8PCGA4p2nQwnlUrOayJj1t8PEFfgaIPAxwA2JYqWurjMEnAKKtmfQwxSlCyHqF1XLaSiMG4VrT8r1wcMFc0TX7pErWd3qo12GjX5AQVgFLOAYbG8lROG4qRVQ2ztcrXPfaZCpD0Dz57MTRUkPG1H8tYsBuBquxOTmroXLko%2Fg5lPBpSKkgxDMZi1kcwlQ6cC2%2FtWbb1e%2FyttDff3uu9WlC8Krmo3jaUf4WdM3ah3o4rUwuZtYWom0LNSJodyxGVKPl9DbIb9vSv8r%2Fqm+SdVCQvWIXCEVsa6gKP6Fk1k+6Kuf92tPGqqGiUN%2F6ZqyehccF6SsIc66n6cR=";
            System.out.println("加密后内容:" + encryptData);
            // RSA解密
            String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
            System.out.println("解密后内容:" + decryptData);
            
//            // RSA签名
//            String sign = sign(data, getPrivateKey(privateKey));
//            // RSA验签
//            boolean result = verify(data, getPublicKey(publicKey), sign);
//            System.out.print("验签结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.print("加解密异常");
        }
    }
}
